////////////////////////////////
//util.lua
//This has general utility functions.
//DEFINES
////////////////////////////////

//This adds to the log file.
function bbb.log(txt)
	bbb.error("LOG","Attempted to log: '"..txt.."' but logging has not been coded.")
end

//This prints to wherever you tell it to, LOG CONSOLE HUD DEBUG
function bbb.print(txt,to,users)
	if(type(txt)!="string") then
		bbb.error("PRINT","Text not specified.")
		return false
	end
	if(type(to)!="number") then //If undefined, print to the console only
		to=bbb.CONSOLE
	end
	local vals=bbb.uncompress(to) //Convert a decimal into binary components
	if(vals[3]==true and bbb.get("log")==true) then //Log it to the log array
		bbb.log(txt)
	end
	if(vals[2]==true) then //Print to console
		print(txt)
	end
	if(vals[1]==true) then //Print to users
		local sendtable
		if(type(users)!="table") then
			bbb.error("PRINT","Users needs to be a table Ex: {player.GetByID(1)}")
			return false
		end
		sendtable=string.Explode("\n",txt)
		for index,user in ipairs(users) do
			if(type(user)!="Player") then
				bbb.error("PRINT","Invalid user in table.")
			else
				for index,message in ipairs(sendtable) do
					user:ConCommand("echo \""..message.."\"\n")
				end
			end
		end
	end
	if(vals[4]==true and bbb.get("debug")==true) then //Debug print
		print("DEBUG: "..txt)
	end
end

function bbb.tprint(tab,to,users,indent)
	if(type(tab)!="table") then
		bbb.error("TABLE PRINT","Table not specified.")
		return false
	end
	indent=indent or 0
	local txt=""
	local tmp
	for k,v in pairs(tab) do
		if(type(v)=="table") then
			tmp=bbb.tprint(v,to,users,indent+1)
			if(type(tmp)!="string") then
				return false
			end
			txt=txt..string.rep(" ",indent)..tostring(k)..":\n"..tmp
		else
			txt=txt..string.rep(" ",indent)..tostring(k)..": "..tostring(v).."\n"
		end
	end
	if(indent==0) then //It isn't recursed...
		bbb.print(string.sub(txt,1,-2),to,users) //The sub takes away the extra newline
	else
		return txt //Allow recursion
	end
end

//This converts an integer number into a table of true/false values. 13->{true,false,true,true}
//It can store a bunch of boolean flags in one integer
function bbb.uncompress(n)
	if(type(n)!="number") then
		bbb.error("UNCOMPRESS","Invalid input.")
		return
	end
	local tbl = {}
	local cnt = 1
	while (n > 0) do
		local last = n % 2
		if(last == 1) then
			tbl[cnt] = true
		else
			tbl[cnt] = false
		end
		n = (n-last)/2
		cnt = cnt + 1
	end
	return tbl
end

//This checks the table "against" against the input "check"
//If checkkey is true it checks against the key, otherwise it checks against the value
function bbb.list(check,against,checkkey)
	if(type(check)!="string" or type(against)!="table") then
		bbb.error("LIST","Bad input types.")
		return false
	end
	local len=string.len(check)
	local checking
	local output={}
	for k,v in pairs(against) do
		if(checkkey==true) then
			checking=k
		else
			checking=v
		end
		if(type(checking)!="string") then
			bbb.error("LIST","Bad check type.")
			return false
		end
		if(string.sub(checking,1,len)==check) then //If there are any matches for the start
			table.insert(output,tostring(checking)) //Add it to the possibilities
		end
	end
	return output
end

function bbb.tablediff(input,against) //This checks input against against, and returns the differences, so we don't have to update everything in the sql.
	if(type(input)!="table" or type(against)!="table") then
		bbb.error("TABLEDIFF","Bad inputs.")
		return {}
	end
	local diff={}
	local tmp
	//If there is stuff in against that isn't in input, it ignores it.
	for k,v in pairs(input) do
		if(type(v)=="table") then //Yay, recurse!
			if(type(against[k])=="table") then //That's good too.
				tmp=bbb.tablediff(v,against[k] or {}) //The or makes sure it isn't nil.
				if(#tmp>0) then //There were differences, record them...
					diff[k]=tmp
				end
			else
				diff[k]=v //There is no comprable table, so everything contained in the table needs to be added.
			end
		else //Not table...
			if(type(v)!=type(against[k])) then //Different types...
				diff[k]=v //Record that it is different.
			else
				//Same types...
				if(v!=against[k]) then //Not equal...
					diff[k]=v //Record that shiz.
				end
			end
		end
	end
	return diff //Return the differences.
end



function bbb.error(area,err)
	//This handles calls to error that do not include an area.
	if(err==nil) then
		err=area
		area="GENERAL"
	end
	//You called the error function without an error.
	if(area==nil) then
		area="GENERAL"
		err="Unspecified error."
	end
	print("ERROR: "..area.." - "..err)
	//Somebody explain this thing to me, it seems to be mumbo jumbo
	//Uncomment if you really can't find a problem.
	//debug.Trace()
end

function bbb.reload()
	local base=bbb.get("luabase")
	bbb.unload() //Everything goes away
	include(base.."main.lua") //Then it comes back
end

function bbb.unload()
	bbb.savesettings() //Save our settings
	for k,v in ipairs(player.GetAll()) do //Save user data.
		bbb.userdatatosql(v)
	end
	concommand.Remove("bbb") //Remove the concommand
	timer.Destroy("bbb.usercheck") //Destroy our user save timer
	timer.Destroy("bbb.sst") //Destroy our settings timer
	bbb=nil
end
